package com.malljelly.study.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.config.AlipayConfig;
import com.malljelly.study.dao.mapper.PaymentInfoMapper;
import com.malljelly.study.dao.po.PaymentInfo;
import com.malljelly.study.feign.OrderFeignClient;
import com.malljelly.study.service.PayCallBackService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * 支付宝同步和异步回调
 *
 * 参考文献
 https://docs.open.alipay.com/270/105902/
 */
@Service
@Slf4j
public class PayCallBackServiceImpl implements PayCallBackService {


    @Autowired
    private PaymentInfoMapper paymentInfoMapper;

    @Autowired
    private OrderFeignClient orderFeignClient;


    /**
     * 同步回调
     * @param params
     * @return
     */
    @Override
    public JSONObject synCallBack(Map<String, String> params) {

        log.info("####同步回调开始####params:",params);
        JSONObject result = new JSONObject();
        try {
           //1.验签
            boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key,
                    AlipayConfig.charset, AlipayConfig.sign_type); // 调用SDK验证签名
            // ——请在这里编写您的程序（以下代码仅作参考）——
            if (!signVerified) {
                result.put("code", -1);
                result.put("msg", "验签失败!");
                return result;
            }
            // 商户订单号
            String out_trade_no = params.get("out_trade_no");
            // 支付宝交易号
            String trade_no = params.get("trade_no");
            // 付款金额
            String total_amount = params.get("total_amount");
            result.put("out_trade_no", out_trade_no);
            result.put("trade_no", trade_no);
            result.put("total_amount", total_amount);
            result.put("code", 0);
            return result;
        } catch (Exception e) {
            log.info("######PayCallBackServiceImpl##ERROR:#####", e);
            result.put("code", -1);
            result.put("msg", "验签失败!");
            return result;
        }finally{
            log.info("####同步回调结束####params:",params);
        }
    }

    /**
     * 异步回调
     * @param params
     * @return
     */
    @Override
    public String asynCallBack(Map<String, String> params) {


        // 获取支付宝GET过来反馈信息
        try {
            log.info("####异步回调开始####params:",params);
            boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key,
                    AlipayConfig.charset, AlipayConfig.sign_type); // 调用SDK验证签名
            // ——请在这里编写您的程序（以下代码仅作参考）——
            if (!signVerified) {
                return "fail";
            }
            // 商户订单号
            String outTradeNo = params.get("out_trade_no");

            //1查询支付信息
            PaymentInfo paymentInfo = paymentInfoMapper.getByOrderIdPayInfo(outTradeNo);
            if(paymentInfo==null){
                return "fail";
            }

            //2 支付幂等性判断,如果已经支付过,返回success,防止重试产生重复 ,可以改成枚举
            Integer state = paymentInfo.getState();
            if (state.equals("1")) {
                return "success";
            }
            // 支付宝交易号
            String trade_no = params.get("trade_no");
            // 交易状态
            String trade_status = params.get("trade_status");

            //3支付成功修改状态
            if (trade_status.equals("TRADE_SUCCESS")) {
                paymentInfo.setPayMessage(params.toString());
                paymentInfo.setPlatformorderId(trade_no);
                paymentInfo.setState(1);
                paymentInfoMapper.updatePayInfo(paymentInfo);

                //4.调用订单服务,这里为了测试分布式事务,采用服务调用,正常情况下应该使用mq,防止超时
                JSONObject result = orderFeignClient.updateOrder(1l, trade_no, outTradeNo);
                Object code = result.get("code");
                if(-1==  Integer.parseInt(code.toString())){
                    return "fail";
                }
                int num = 1 / 0;
            }
            return "success";
        } catch (Exception e) {
            log.error("####支付宝异步通知出现异常,ERROR:", e);
            return "fail";
        }finally{
            log.info("#####支付宝异步通知synCallBack#####结束,params:{}", params);
        }

    }





}
